import 'dart:async';

/// 轮询请求API的通用类
class PollingManager<T> {
  final Future<T> Function() apiCall;
  final bool Function(T) isDataValid;
  final Duration initialDelay;
  final Duration maxDelay;
  final Duration dataReceivedDelay;
  final int maxRetries;
  final bool immediateFirstRequest;
  final Duration? timeout;

  late Duration _currentDelay;
  int _retryCount = 0;
  StreamController<T>? _controller;
  Timer? _timer;
  bool _isPolling = false;

  PollingManager({
    required this.apiCall,
    required this.isDataValid,
    this.initialDelay = const Duration(seconds: 1),
    this.maxDelay = const Duration(seconds: 30),
    this.dataReceivedDelay = const Duration(seconds: 2),
    this.maxRetries = -1,
    this.immediateFirstRequest = true,
    this.timeout,
  }) : _currentDelay = initialDelay;

  /// 开始轮询并返回结果流
  Stream<T> startPolling() {
    if (_isPolling) {
      throw Exception('Polling is already running');
    }

    _isPolling = true;
    _controller = StreamController<T>.broadcast(
      onCancel: () => stopPolling(),
    );

    // 立即执行第一次请求或等待初始延迟
    if (immediateFirstRequest) {
      _performRequest();
    } else {
      _scheduleNextRequest(_currentDelay);
    }

    return _controller!.stream;
  }

  /// 停止轮询
  void stopPolling() {
    _isPolling = false;
    _timer?.cancel();
    _controller?.close();
    _controller = null;
    _retryCount = 0;
    _currentDelay = initialDelay;
  }

  /// 执行API请求
  Future<void> _performRequest() async {
    if (!_isPolling || _controller!.isClosed ?? true) {
      return;
    }

    try {
      T result;

      // 处理超时
      if (timeout != null) {
        result = await apiCall().timeout(
          timeout!,
          onTimeout: () => throw TimeoutException("Request timed out"),
        );
      } else {
        result = await apiCall();
      }

      // 重置重试计数，因为请求成功
      _retryCount = 0;

      // 发送结果
      _controller!.add(result);

      // 根据数据有效性调整延迟
      _currentDelay = isDataValid(result)
          ? dataReceivedDelay
          : _calculateNextDelay(growthFactor: 2);

      // 安排下一次请求
      _scheduleNextRequest(_currentDelay);
    } catch (e) {
      // 处理错误
      if (e is TimeoutException || e is Exception) {
        // 检查是否达到最大重试次数
        if (maxRetries != -1 && _retryCount >= maxRetries) {
          _controller?.addError(e);
          stopPolling();
          return;
        }

        // 增加重试计数并计算下一次延迟（指数退避）
        _retryCount++;
        _currentDelay = _calculateNextDelay(growthFactor: 2);

        // 发送错误但继续轮询
        _controller?.addError(e);

        // 安排下一次重试
        _scheduleNextRequest(_currentDelay);
      } else {
        // 未知错误，停止轮询
        _controller?.addError(e);
        stopPolling();
      }
    }
  }

  /// 计算下一次延迟时间（不超过最大延迟）
  Duration _calculateNextDelay({required double growthFactor}) {
    final nextDelay = Duration(
        milliseconds: (_currentDelay.inMilliseconds * growthFactor).toInt()
    );
    return nextDelay <= maxDelay ? nextDelay : maxDelay;
  }

  /// 安排下一次请求
  void _scheduleNextRequest(Duration delay) {
    _timer?.cancel();
    _timer = Timer(delay, _performRequest);
  }

  /// 检查是否正在轮询
  bool get isPolling => _isPolling;
}

// 使用示例
class DataFetcher {
  // 模拟API请求
  Future<String?> fetchData() async {
    await Future.delayed(const Duration(milliseconds: 500));

    // 70%概率返回有效数据，30%概率返回空
    if (DateTime.now().microsecond % 10 < 7) {
      return "New data: ${DateTime.now().toIso8601String()}";
    } else {
      // 模拟空数据或无效数据
      return null;
    }
  }
}

// 在Widget中使用
/*
class PollingExampleWidget extends StatefulWidget {
  @override
  _PollingExampleWidgetState createState() => _PollingExampleWidgetState();
}

class _PollingExampleWidgetState extends State<PollingExampleWidget> {
  late PollingManager<String?> _pollingManager;
  final DataFetcher _dataFetcher = DataFetcher();
  String? _latestData;
  String? _errorMessage;

  @override
  void initState() {
    super.initState();

    // 初始化轮询管理器
    _pollingManager = PollingManager(
      apiCall: _dataFetcher.fetchData,
      isDataValid: (data) => data != null && data.isNotEmpty,
      initialDelay: const Duration(seconds: 1),
      maxDelay: const Duration(seconds: 10),
      dataReceivedDelay: const Duration(seconds: 2),
      maxRetries: 5,
      timeout: const Duration(seconds: 3),
    );

    // 开始轮询
    _startPolling();
  }

  void _startPolling() {
    _pollingManager.startPolling().listen(
      (data) {
        setState(() {
          _latestData = data;
          _errorMessage = null;
        });
      },
      onError: (error) {
        setState(() {
          _errorMessage = error.toString();
        });
      },
    );
  }

  @override
  void dispose() {
    // 停止轮询以防止内存泄漏
    _pollingManager.stopPolling();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Polling Example")),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            if (_errorMessage != null)
              Text(
                "Error: $_errorMessage",
                style: const TextStyle(color: Colors.red),
              ),
            if (_latestData != null)
              Text("Latest Data: $_latestData"),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                if (_pollingManager.isPolling) {
                  _pollingManager.stopPolling();
                } else {
                  _startPolling();
                }
                setState(() {});
              },
              child: Text(
                _pollingManager.isPolling ? "Stop Polling" : "Start Polling",
              ),
            ),
          ],
        ),
      ),
    );
  }
}
*/
